home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / langs / c68_445b.zoo / src / cc68x / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-01  |  11.6 KB  |  534 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <support.h>
  4. #include <unistd.h>
  5. #include "global.h"
  6. #include "patchlev.h"
  7.  
  8. #define CPP        "cpp"
  9. #define CC1        "c68"
  10. #define AS        "as68"
  11. #define LNK        "ld"
  12. #define RT_STARTUP    "%scrt0.o"
  13. #define    N_LIB_FORMS    2
  14. #define INC_ENV_VAR    "C68INC"
  15. #define LIB_ENV_VAR    "C68LIB"
  16. #define DEFAULT_INC    "c:\\c68\\include"
  17. #define DEFAULT_LIB    "c:\\c68\\lib"
  18. #define DEFAULT_EXEC    "a.out"
  19.  
  20. #define DO_PREPROCESS    0
  21. #define DO_COMPILE    1
  22. #define DO_ASSEMBLE    2
  23. #define DO_LINK        3
  24. #define UP_TO_LINK    (last_stage == DO_LINK ? DO_ASSEMBLE : last_stage)
  25.  
  26. #define LF_STARTUP    1
  27. #define LF_MATHLIB    2
  28. #define LF_STDCLIB    3
  29.  
  30. #define RM_INTERMED    1
  31. #define RM_FINAL    2
  32.  
  33. #define DEFAULT_WARN_LVL    3
  34.  
  35. #ifdef __STDC__
  36. static void usage(void);
  37. static void rename_stage(const char *);
  38. static void long_option(const char *);
  39. static char *lib_name_opts(const char *, int);
  40. static void add_lib(const char *);
  41. static void add_lib_file(int);
  42. static void add_input_file(const char *, int);
  43. static void remove_temp_files(int);
  44. static void panic_remove_temps(void);
  45. static const char *derive_dest(const char *, int);
  46. static void process_file(const char *, int);
  47. #else
  48. static void usage();
  49. static void rename_stage();
  50. static void long_option();
  51. static char *lib_name_opts();
  52. static void add_lib();
  53. static void add_lib_file();
  54. static void add_input_file();
  55. static void remove_temp_files();
  56. static void panic_remove_temps();
  57. static char *derive_dest();
  58. static void process_file();
  59. #endif
  60.  
  61. static Arguments cpp_args = {0, 0, 0},
  62.          cc1_args = {0, 0, 0},
  63.          as_args = {0, 0, 0},
  64.          lnk_args = {0, 0, 0},
  65.          c_files = {0, 0, 0},
  66.          i_files = {0, 0, 0},
  67.          s_files = {0, 0, 0},
  68.          o_files = {0, 0, 0},
  69.          new_env = {0, 0, 0},
  70.          temp_files = {0, 0, 0};
  71. static Arguments *passes[] = {&cpp_args, &cc1_args, &as_args, &lnk_args};
  72. static Arguments *pass_inputs[] = {&c_files, &i_files, &s_files, &o_files};
  73.  
  74. static char const *cpp_init_args[] = {CPP, "-S", "-D__TOS__", "-D__C68__", NULL},
  75.           *cc1_init_args[] = {CC1, NULL},
  76.           *as_init_args[] = {AS, NULL},
  77.           *lnk_init_args[] = {LNK, NULL},
  78.           *cpp_ansi_args[] = {"-ansi", "-T", NULL},
  79. #if 0
  80.           *fplib_args[] = {"-u", "__doprnt", "-u", "__scanf", NULL},
  81. #endif
  82.           *cpp_asm_args[] = {"-P0", "-Wno-bad-chars",
  83.                      "-Wno-bad-concat-tokens", NULL};
  84. #define N_CPP_ASM_ARGS    3
  85.  
  86. char *argv0;
  87. int action = 1,
  88.     verbose = 0;
  89.  
  90. static const char *INCLUDE, *LIB, *TMPDIR, *outfnam = 0;
  91. static int last_stage = DO_LINK,
  92.        fp_lib = 0,
  93.        debug = 0,
  94.        keep = 0,
  95.        warn_level = DEFAULT_WARN_LVL,
  96.        long_int = 0,
  97.        profile = 0,
  98.        ansi = 1;
  99.  
  100. static void usage()
  101. {
  102.   fprintf(stderr, "usage: %s {args}\n", argv0);
  103.   exit(0);
  104. }
  105.  
  106. static void long_option(s)
  107.   const char *s;
  108. {
  109.   if (strcmp(s, "-mshort") == 0)
  110.     long_int = 0;
  111.   else if (strcmp(s, "-mlong") == 0)
  112.     long_int = 1;
  113.   else if (strcmp(s, "-ansi") == 0)
  114.     ansi = 1;
  115.   else if (strcmp(s, "-trad") == 0)
  116.     ansi = 0;
  117.   else {
  118.     error("unrecognized option '%s'", s);
  119.     usage();
  120.   }
  121. }
  122.  
  123. static void rename_stage(param)
  124.   const char *param;
  125. {
  126.   static char errmsg[] = "Invalid -N argument %s";
  127.  
  128.   if (param[1] != '=') {
  129.     error(errmsg, param);
  130.     return;
  131.   }
  132.   switch (*param) {
  133.     case 'P':
  134.       cpp_args._args[0] = param + 2;
  135.       return;
  136.     case 'C':
  137.       cc1_args._args[0] = param + 2;
  138.       return;
  139.     case 'A':
  140.       as_args._args[0] = param + 2;
  141.       return;
  142.     case 'L':
  143.       lnk_args._args[0] = param + 2;
  144.       return;
  145.     default:
  146.       error(errmsg, param);
  147.   }
  148. }
  149.  
  150. static char *lib_name_opts(lnam, which)
  151.   const char *lnam;
  152.   int which;
  153. {
  154.   static char buf[128];
  155.  
  156.   switch (which) {
  157.     case 1:
  158.       sprintf(buf, "lib%s%s%s.a", lnam, (profile ? "p" : ""),
  159.           (long_int ? "32" : ""));
  160.       return buf;
  161.     case 2:
  162.       sprintf(buf, "%s.%c%s", lnam, (profile ? 'p' : 'l'),
  163.           (long_int ? "32" : profile ? "lb" : "ib"));
  164.       return buf;
  165.    default:
  166.       bugchk("lib_name_opts(%d)?", which);
  167.       return 0;
  168.   }
  169. }
  170.  
  171. static void add_lib(lnam)
  172.   const char *lnam;
  173. {
  174.   char *s;
  175.   int i;
  176.  
  177.   for (i = 1; i <= N_LIB_FORMS; i++) {
  178.     s = lib_name_opts(lnam, i);
  179.     s = findfile(s, LIB, (char * const *)0);
  180.     if (s)
  181.       break;
  182.   }
  183.   if (s)
  184.     add_arg(&o_files, strdup(s));
  185.   else
  186.     error("no corresponding library found for parameter -l%s", lnam);
  187. }
  188.  
  189. static void add_lib_file(which)
  190.   int which;
  191. {
  192.   switch (which) {
  193.     case LF_STARTUP:
  194.       {
  195.     char *s = mallok(strlen(RT_STARTUP) + 1);
  196.  
  197.     sprintf(s, RT_STARTUP, (profile ? "p" : ""));
  198.     add_arg(&o_files, s);
  199.       }
  200.       break;
  201.     case LF_MATHLIB:
  202.       add_lib("m");
  203.       break;
  204.     case LF_STDCLIB:
  205.       add_lib("c");
  206.       break;
  207.     default:
  208.       bugchk("add_lib_file(%d)?", which);
  209.   }
  210. }
  211.  
  212. static void add_input_file(fnam, stage)
  213.   const char *fnam;
  214.   int stage;
  215. {
  216.   add_arg(pass_inputs[stage], fnam);
  217.   if (last_stage == DO_LINK && stage <= DO_ASSEMBLE)
  218.     add_arg(&o_files, derive_dest(fnam, DO_ASSEMBLE));
  219. }
  220.  
  221. static void remove_temp_files(state)
  222.   int state;
  223. {
  224.   char const **p;
  225.  
  226.   if (temp_files.nargs == 0 || args(&temp_files) == 0 || keep)
  227.     return;
  228.  
  229.   temp_files.nargs = 0;
  230.   for (p = args(&temp_files); *p; p++) {
  231.     if ((*p)[strlen(*p) - 1] == 'o' && state == RM_INTERMED) {
  232.       args(&temp_files)[temp_files.nargs++] = *p;
  233.     } else {
  234.       if (verbose || !action)
  235.     printf("rm -f %s\n", *p);
  236.       if (action)
  237.     unlink(*p);
  238.       free(*p);
  239.     }
  240.   }
  241.   args(&temp_files)[temp_files.nargs] = 0;
  242. }
  243.  
  244. static void panic_remove_temps()
  245. {
  246.   action = 1;
  247.   verbose = 0;
  248.   remove_temp_files(RM_FINAL);
  249. }
  250.  
  251. static const char *derive_dest(fnam, stage)
  252.   const char *fnam;
  253.   int stage;
  254. {
  255.   static char exts[] = {'i', 's', 'o'};
  256.   char *s = mallok(2 + strlen(fnam) + strlen(TMPDIR));
  257.   const char *t = strrchr(fnam, '.');
  258.  
  259.   if (!t)
  260.     bugchk("in derive_dest():  \"%s\" has no extension", fnam);
  261.  
  262.   if (stage == last_stage && outfnam)
  263.     return outfnam;
  264.  
  265.   sprintf(s, "%.*s.%c", (int)(t - fnam), fnam, exts[stage]);
  266.   if (stage < last_stage && access(s, F_OK) < 0) {
  267.     register const char **p;
  268.  
  269.     sprintf(s, "%s\\%.*s.%c", TMPDIR, (int)(t - fnam), fnam, exts[stage]);
  270.     /* Temporary .o files might already be on the list; check to avoid
  271.        duplicates. */
  272.     for (p = args(&temp_files); p && *p; p++) {
  273.       if (strcmp(*p, s) == 0)
  274.     break;
  275.     }
  276.     if (!p || !*p)
  277.       add_arg(&temp_files, s);
  278.   }
  279.   return s;
  280. }
  281.  
  282. static void process_file(fnam, first_stage)
  283.   const char *fnam;
  284.   int first_stage;
  285. {
  286.   int i, cpp_asm_flag = 0;
  287.   const char *inf = fnam;
  288.   const char *outf;
  289.  
  290.   if (first_stage == DO_PREPROCESS) {
  291.     const char *t = strrchr(fnam, '.');
  292.  
  293.     if (!t)
  294.       bugchk("in process_file():  \"%s\" has no extension", fnam);
  295.     cpp_asm_flag = ((strcmp(t + 1, "cpp") == 0) ||
  296.             (strcmp(t + 1, "spp") == 0));
  297.     if (cpp_asm_flag) {
  298.       add_args(&cpp_args, cpp_asm_args);
  299.       if (last_stage < DO_COMPILE)
  300.     error("-P/-E flags incompatible with input file %s", fnam);
  301.     }
  302.   }
  303.  
  304.   for (i = first_stage; i <= UP_TO_LINK; i++) {
  305.     outf = derive_dest(fnam, i + (cpp_asm_flag && i == DO_PREPROCESS));
  306.     add_arg(passes[i], inf);
  307.     add_arg(passes[i], outf);
  308.     run(passes[i], args(&new_env));
  309.     remove_args(passes[i], 2);
  310.     inf = outf;
  311.     if (cpp_asm_flag && i == DO_PREPROCESS)
  312.       i++;
  313.   }
  314.   if (cpp_asm_flag)
  315.     remove_args(&cpp_args, N_CPP_ASM_ARGS);
  316. #if 0
  317.   if (last_stage == DO_LINK)
  318.     add_arg(&o_files, outf);
  319. #endif
  320.   remove_temp_files(RM_INTERMED);
  321. }
  322.  
  323. int main(argc, argv, envp)
  324.   int argc;
  325.   char **argv;
  326.   char **envp;
  327. {
  328.   int i;
  329.   int got_file_args = 0;
  330.   char *s;
  331.   const char **p;
  332.  
  333.   if (argc == 1)
  334.     usage();
  335.   argv0 = argv[0];
  336.   atexit(panic_remove_temps);
  337.  
  338.   add_args(&cpp_args, cpp_init_args);
  339.   add_args(&cc1_args, cc1_init_args);
  340.   add_args(&as_args, as_init_args);
  341.   add_args(&lnk_args, lnk_init_args);
  342.   add_lib_file(LF_STARTUP);
  343.  
  344.   if (!(INCLUDE = getenv(INC_ENV_VAR)))
  345.     INCLUDE = DEFAULT_INC;
  346.   if (!(LIB = getenv(LIB_ENV_VAR)))
  347.     LIB = DEFAULT_LIB;
  348.   s = mallok(9 + strlen(INCLUDE));
  349.   sprintf(s, "INCLUDE=%s", INCLUDE);
  350.   add_arg(&new_env, s);
  351.   s = mallok(5 + strlen(LIB));
  352.   sprintf(s, "LIB=%s", LIB);
  353.   add_arg(&new_env, s);
  354.   add_args(&new_env, (char const * const *)envp);
  355.  
  356.   TMPDIR = getenv("TEMP");
  357.   if (!TMPDIR)
  358.     TMPDIR = getenv("TMP");
  359.   if (!TMPDIR)
  360.     TMPDIR = getenv("TMPDIR");
  361.   if (!TMPDIR)
  362.     TMPDIR = ".";
  363. #ifdef __MINT__
  364.   /* if temp dir is in Unix format, change it to DOS format so that jas
  365.      doesn't get confused */
  366.   if (strchr(TMPDIR, '/') != 0) {
  367.     static char dos_tmpdir[128];
  368.  
  369.     _unx2dos(TMPDIR, dos_tmpdir);
  370.     TMPDIR = dos_tmpdir;
  371.   }
  372. #endif
  373.  
  374.   for (i = 1; i < argc; i++) {
  375.     if (argv[i][0] == '-') {
  376.       switch(argv[i][1]) {
  377.     case 'E':
  378.       outfnam = "-";
  379.       /* and fall through */
  380.     case 'P':
  381.       last_stage = DO_PREPROCESS;
  382.       break;
  383.     case 'S':
  384.       last_stage = DO_COMPILE;
  385.       break;
  386.     case 'c':
  387.       last_stage = DO_ASSEMBLE;
  388.       break;
  389.     case 'D':
  390.     case 'U':
  391.     case 'I':
  392.       add_arg(&cpp_args, argv[i]);
  393.       break;
  394.     case 'O':
  395.       add_arg(&cc1_args, argv[i]);
  396.       break;
  397.     case 'L':
  398.       add_arg(&lnk_args, argv[i]);
  399.       break;
  400.     case 'N':
  401.       rename_stage(argv[i] + 2);
  402.       break;
  403.     case 'o':
  404.       outfnam = argv[++i];
  405.       break;
  406.     case 'l':
  407.       add_lib(argv[i] + 2);
  408.       break;
  409.     case 'f':
  410.       fp_lib = 1;
  411.       break;
  412.     case 'g':
  413.       debug = 1;
  414.       break;
  415.     case 'n':
  416.       action = 0;
  417.       break;
  418.     case 'v':
  419.       verbose++;
  420.       break;
  421.     case 't':
  422.       keep = 1;
  423.       break;
  424.     case 'p':
  425.       profile = 1;
  426.       break;
  427.     case 'W':
  428.       {
  429.         char c = argv[i][2];
  430.  
  431.         if (!c || c < '0' || c > '7' || argv[i][3]) {
  432.           error("invalid warning level '%s'", argv[i] + 2);
  433.           warn_level = DEFAULT_WARN_LVL;
  434.         } else
  435.           warn_level = c - '0';
  436.       }
  437.       break;
  438.     case 'V':
  439.       fprintf(stderr, "cc68x v%d.%d.%d\n",
  440.           MAJOR_VERSION, MINOR_VERSION, PATCH_LEVEL);
  441.       break;
  442.     default:
  443.       long_option(argv[i]);
  444.       }
  445.     } else if (argv[i][0] == '+') {
  446.       switch (argv[i][1]) {
  447.     case 'P':
  448.       add_arg(&cpp_args, argv[i] + 2);
  449.       break;
  450.     case 'C':
  451.       add_arg(&cc1_args, argv[i] + 2);
  452.       break;
  453.     case 'A':
  454.       add_arg(&as_args, argv[i] + 2);
  455.       break;
  456.     case 'L':
  457.       add_arg(&lnk_args, argv[i] + 2);
  458.       break;
  459.     default:
  460.       error("unrecognized option '%s'", argv[i]);
  461.       usage();
  462.       }
  463.     } else {
  464.       got_file_args = 1;
  465.       s = strrchr(argv[i], '.');
  466.       if (!s)
  467.     add_input_file(argv[i], DO_LINK);
  468.       else if (s[1] == 'c' && s[2] == '\0')
  469.     add_input_file(argv[i], DO_PREPROCESS);
  470.       else if ((strcmp(s + 1, "cpp") == 0) ||
  471.            (strcmp(s + 1, "spp") == 0))
  472.     add_input_file(argv[i], DO_PREPROCESS);
  473.       else if (s[1] == 'i' && s[2] == '\0')
  474.     add_input_file(argv[i], DO_COMPILE);
  475.       else if (s[1] == 's' && s[2] == '\0')
  476.     add_input_file(argv[i], DO_ASSEMBLE);
  477.       else
  478.     add_input_file(argv[i], DO_LINK);
  479.     }
  480.   }
  481.  
  482.   if (got_file_args == 0)
  483.     fatal("no files specified");
  484.  
  485. #if 0
  486.   if (fp_lib)
  487.     add_args(&lnk_args, fplib_args);
  488. #endif
  489.   if (debug) {
  490.     add_arg(&cc1_args, "-g");
  491.     add_arg(&as_args, "-L1");
  492.     add_arg(&lnk_args, "-t");
  493.   }
  494.   if (verbose > 1) {
  495.     add_arg(&cpp_args, "-V");
  496.     add_arg(&cc1_args, "-v");
  497.     add_arg(&as_args, "-v");
  498.     add_arg(&lnk_args, "-v");
  499.   }
  500.   if (long_int) {
  501.     add_arg(&cc1_args, "-noshort");
  502.   } else {
  503.     add_arg(&cpp_args, "-D__MSHORT__");
  504.   }
  505.   if (ansi)
  506.     add_args(&cpp_args, cpp_ansi_args);
  507.   else
  508.     add_arg(&cc1_args, "-trad");
  509.   if (warn_level != DEFAULT_WARN_LVL) {
  510.     static char warn_opt[] = "-warn=3";
  511.  
  512.     warn_opt[6] = (char)(warn_level + '0');
  513.     add_arg(&cc1_args, warn_opt);
  514.   }
  515.  
  516.   for (i = DO_PREPROCESS; i <= UP_TO_LINK; i++) {
  517.     for (p = args(pass_inputs[i]); p && *p; p++) {
  518.       process_file(*p, i);
  519.     }
  520.   }
  521.   if (last_stage == DO_LINK) {
  522.     if (fp_lib)
  523.       add_lib_file(LF_MATHLIB);
  524.     add_lib_file(LF_STDCLIB);
  525.     add_arg(&lnk_args, "-o");
  526.     add_arg(&lnk_args, (outfnam ? outfnam : DEFAULT_EXEC));
  527.     add_args(&lnk_args, args(&o_files));
  528.     run(&lnk_args, args(&new_env));
  529.   }
  530.  
  531.   remove_temp_files(RM_FINAL);
  532.   return 0;
  533. }
  534.